#include "volumecontrolwidget.h"


#include <windows.h>
#include <mmdeviceapi.h>
#include <audiopolicy.h>
#include <endpointvolume.h>
#include <psapi.h>
#include <iostream>
#include <vector>
#include <string>
#include <QDebug>
#include <functiondiscoverykeys_devpkey.h>
#include <algorithm>

#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "version.lib")  // 新增：链接version.lib
// 新增：链接窗口管理库 user32.lib
#pragma comment(lib, "user32.lib")


// 音频会话信息结构体
struct AudioSessionInfo {
    std::wstring appName;       // 应用程序名称
    DWORD processId;            // 进程ID
    float volume;               // 当前音量(0.0-1.0)
    BOOL  isMuted;               // 是否静音
    IAudioSessionControl2* sessionControl; // 会话控制接口
};


struct AudioSessionInfo2 {
    QString name;          // 应用程序名称或系统声音
    QString exeName;       // EXE文件名
    DWORD processId;       // 进程ID
    int volume;            // 音量百分比(0-100)
    bool isSystemSound;    // 是否为系统声音
};


// 释放COM接口的工具函数
template <typename T>
void SafeRelease(T*& ptr) {
    if (ptr) {
        ptr->Release();
        ptr = nullptr;
    }
}

// 通过进程ID获取应用程序名称
std::wstring GetProcessName(DWORD processId) {
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); // 要高权限，获取应用程序模块名
    // HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
    // PROCESS_QUERY_LIMITED_INFORMATION权限是 Windows Vista 及以上系统专门为 “有限信息查询” 设计的低权限，普通用户进程默认即可获取，无需管理员权限。
    if (!hProcess ) {
        return L"未知进程";
    }

    WCHAR szProcessName[MAX_PATH] = {0};
    HMODULE hMod;
    DWORD cbNeeded;

    if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
        GetModuleBaseNameW(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(WCHAR));
    }

    CloseHandle(hProcess);
    return szProcessName;
}
// 通过进程ID获取应用程序路径， 再分割成应用程序名称 // PROCESS_QUERY_LIMITED_INFORMATION  低权限
std::wstring GetProcessNameByPid(DWORD pid) {
    HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
    if (!hProc)
         return L"未知进程";
    WCHAR path[MAX_PATH];
    DWORD size = MAX_PATH;
    if (QueryFullProcessImageNameW(hProc, 0, path, &size)) {
        CloseHandle(hProc);
        std::wstring wpath(path, size);
        size_t pos = wpath.find_last_of(L"\\/");
        std::wstring wname = (pos != std::wstring::npos) ? wpath.substr(pos + 1) : wpath;
        return (wname);
    }
    CloseHandle(hProc);
    // return "";
    return L"未知进程";
}


// 枚举所有音频会话
std::vector<AudioSessionInfo> EnumAudioSessions() {
    std::vector<AudioSessionInfo> sessions;
    IMMDeviceEnumerator* pEnumerator = nullptr;
    IMMDevice* pDevice = nullptr;
    IAudioSessionManager2* pSessionManager = nullptr;
    IAudioSessionEnumerator* pSessionEnumerator = nullptr;
    int sessionCount = 0;

    // 初始化COM
    CoInitialize(nullptr);

    try {
        // 创建设备枚举器
        if (CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
            CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator) != S_OK) {
            throw std::exception("error 71");
        }

        // 获取默认音频渲染设备
        if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice) != S_OK) {
            throw std::exception("error 76");
        }

        // 激活音频会话管理器
        if (pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL,
            nullptr, (void**)&pSessionManager) != S_OK) {
            throw std::exception("error 82");
        }

        // 枚举所有音频会话
        if (pSessionManager->GetSessionEnumerator(&pSessionEnumerator) != S_OK) {
            throw std::exception("error 87");
        }

        if (pSessionEnumerator->GetCount(&sessionCount) != S_OK) {
            throw std::exception("error 91");
        }

        // 遍历所有会话
        for (int i = 0; i < sessionCount; i++) {
            IAudioSessionControl* pSessionControl = nullptr;
            IAudioSessionControl2* pSessionControl2 = nullptr;
            ISimpleAudioVolume* pSimpleVolume = nullptr;
            AudioSessionInfo sessionInfo;

            // 获取会话控制接口
            if (pSessionEnumerator->GetSession(i, &pSessionControl) != S_OK) {
                continue;
            }

            // 查询扩展接口
            if (pSessionControl->QueryInterface(__uuidof(IAudioSessionControl2),
                (void**)&pSessionControl2) != S_OK) {
                SafeRelease(pSessionControl);
                continue;
            }

            // 获取进程ID
            if (pSessionControl2->GetProcessId(&sessionInfo.processId) != S_OK) {
                SafeRelease(pSessionControl2);
                SafeRelease(pSessionControl);
                continue;
            }

            // 获取应用程序名称
            sessionInfo.appName = GetProcessNameByPid(sessionInfo.processId);

            // 获取音量控制接口
            if (pSessionControl2->QueryInterface(__uuidof(ISimpleAudioVolume),
                (void**)&pSimpleVolume) != S_OK) {
                SafeRelease(pSessionControl2);
                SafeRelease(pSessionControl);
                continue;
            }

            // 获取当前音量
            pSimpleVolume->GetMasterVolume(&sessionInfo.volume);

            // 获取静音状态
            pSimpleVolume->GetMute(&sessionInfo.isMuted);

            // 保存会话控制接口（用于后续设置音量）
            sessionInfo.sessionControl = pSessionControl2;
            pSessionControl2->AddRef(); // 增加引用计数，防止被释放

            sessions.push_back(sessionInfo);

            // 释放临时接口
            SafeRelease(pSimpleVolume);
            SafeRelease(pSessionControl);
        }
    }
    catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
    }

    // 释放资源
    SafeRelease(pSessionEnumerator);
    SafeRelease(pSessionManager);
    SafeRelease(pDevice);
    SafeRelease(pEnumerator);

    return sessions;
}



/**
 * 获取所有音频会话的音量信息（包括系统声音和应用程序）
 * @param masterVolume 输出参数：系统主音量
 * @return 所有音频会话的信息列表
 */
QList<AudioSessionInfo2> GetAllAudioVolumes(int& masterVolume) {
    QList<AudioSessionInfo2> sessions;
    masterVolume = -1;
    HRESULT hr;

    // 初始化COM
    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED(hr)) {
        return sessions;
    }

    // 获取系统主音量
    IMMDeviceEnumerator* pEnumerator = NULL;
    if (SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
                                  CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
                                  (void**)&pEnumerator))) {
        IMMDevice* pDevice = NULL;
        if (SUCCEEDED(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice))) {
            IAudioEndpointVolume* pEndpointVolume = NULL;
            if (SUCCEEDED(pDevice->Activate(__uuidof(IAudioEndpointVolume),
                                          CLSCTX_ALL, NULL, (void**)&pEndpointVolume))) {
                float vol;
                if (SUCCEEDED(pEndpointVolume->GetMasterVolumeLevelScalar(&vol))) {
                    masterVolume = static_cast<int>(vol * 100);
                }
                pEndpointVolume->Release();
            }
            pDevice->Release();
        }
        pEnumerator->Release();
    }

    // // 枚举所有音频会话获取应用程序音量
    // IAudioSessionManager2* pSessionManager = NULL;
    // if (SUCCEEDED(CoCreateInstance(__uuidof(AudioSessionManager2), NULL,
    //                               CLSCTX_ALL, __uuidof(IAudioSessionManager2),
    //                               (void**)&pSessionManager))) {
    //     IAudioSessionEnumerator* pSessionEnum = NULL;
    //     if (SUCCEEDED(pSessionManager->GetSessionEnumerator(&pSessionEnum))) {
    //         int count = 0;
    //         pSessionEnum->GetCount(&count);

    //         for (int i = 0; i < count; i++) {
    //             IAudioSessionControl* pSessionControl = NULL;
    //             if (SUCCEEDED(pSessionEnum->GetSession(i, &pSessionControl))) {
    //                 AudioSessionInfo info;
    //                 info.volume = -1;
    //                 info.isSystemSound = false;
    //                 info.processId = 0;

    //                 // 获取会话显示名称
    //                 LPWSTR pDisplayName = NULL;
    //                 if (SUCCEEDED(pSessionControl->GetDisplayName(&pDisplayName)) && pDisplayName) {
    //                     info.name = QString::fromWCharArray(pDisplayName);
    //                     CoTaskMemFree(pDisplayName);
    //                 }

    //                 // 判断是否为系统声音
    //                 if (info.name.contains("系统声音") || info.name.contains("System Sounds")) {
    //                     info.isSystemSound = true;
    //                 }

    //                 // 获取进程ID
    //                 IAudioSessionControl2* pSessionControl2 = NULL;
    //                 if (SUCCEEDED(pSessionControl->QueryInterface(__uuidof(IAudioSessionControl2),
    //                                                             (void**)&pSessionControl2))) {
    //                     pSessionControl2->GetProcessId(&info.processId);
    //                     pSessionControl2->Release();
    //                 }

    //                 // 获取进程信息（名称和EXE文件名）
    //                 if (info.processId != 0 && !info.isSystemSound) {
    //                     getProcessInfo(info.processId, info.name, info.exeName);
    //                 } else if (info.isSystemSound) {
    //                     info.exeName = "System Sounds";
    //                 } else {
    //                     info.name = "未知会话";
    //                     info.exeName = "unknown.exe";
    //                 }

    //                 // 获取会话音量
    //                 ISimpleAudioVolume* pSimpleVolume = NULL;
    //                 if (SUCCEEDED(pSessionControl->QueryInterface(__uuidof(ISimpleAudioVolume),
    //                                                             (void**)&pSimpleVolume))) {
    //                     float vol;
    //                     if (SUCCEEDED(pSimpleVolume->GetMasterVolume(&vol))) {
    //                         info.volume = static_cast<int>(vol * 100);
    //                     }
    //                     pSimpleVolume->Release();
    //                 }

    //                 if (info.volume != -1) {
    //                     sessions.append(info);
    //                 }

    //                 pSessionControl->Release();
    //             }
    //         }
    //         pSessionEnum->Release();
    //     }
    //     pSessionManager->Release();
    // }

    CoUninitialize();
    return sessions;
}



// 设置指定会话的音量(0.0-1.0)
bool SetSessionVolume(IAudioSessionControl2* sessionControl, float volume) {
    if (!sessionControl || volume < 0.0f || volume > 1.0f) {
        return false;
    }

    ISimpleAudioVolume* pSimpleVolume = nullptr;
    bool result = false;

    if (sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pSimpleVolume) == S_OK) {
        result = (pSimpleVolume->SetMasterVolume(volume, nullptr) == S_OK);
        SafeRelease(pSimpleVolume);
    }

    return result;
}

// 设置指定会话的静音状态
bool SetSessionMute(IAudioSessionControl2* sessionControl, bool mute) {
    if (!sessionControl) {
        return false;
    }

    ISimpleAudioVolume* pSimpleVolume = nullptr;
    bool result = false;

    if (sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pSimpleVolume) == S_OK) {
        result = (pSimpleVolume->SetMute(mute, nullptr) == S_OK);
        SafeRelease(pSimpleVolume);
    }

    return result;
}




// 辅助函数：从版本信息中提取指定字段（如ProductName）
QString GetStringFromVersionInfo(const BYTE* pVersionInfo, const QString& subBlock) {
    UINT len = 0;
    LPVOID pBuffer = nullptr;
    WCHAR* pwszValue = nullptr;

    // 转换为宽字符子块名（如L"\\StringFileInfo\\080404B0\\ProductName"）
    std::wstring subBlockW = subBlock.toStdWString();

    // 获取版本信息中指定字段的地址
    if (!VerQueryValueW(const_cast<BYTE*>(pVersionInfo),
                       subBlockW.c_str(),
                       &pBuffer,
                       &len) || len == 0) {
        return QString();
    }

    pwszValue = static_cast<WCHAR*>(pBuffer);
    return QString::fromWCharArray(pwszValue);
}

// 根据进程ID获取显示名称（如“微信”而非“WeChat.exe”）
QString GetProcessDisplayName(DWORD processId) {
    // 1. 打开进程获取句柄
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                                 FALSE, processId);
    if (!hProcess || hProcess == INVALID_HANDLE_VALUE) {
        return QStringLiteral("未知进程");
    }

    // 2. 获取进程可执行文件路径
    WCHAR szExePath[MAX_PATH] = {0};
    if (!GetModuleFileNameExW(hProcess, nullptr, szExePath, MAX_PATH)) {
        CloseHandle(hProcess);
        return QStringLiteral("未知进程");
    }
    CloseHandle(hProcess);

    // 3. 获取版本信息大小
    DWORD dwHandle = 0;
    DWORD dwVersionInfoSize = GetFileVersionInfoSizeW(szExePath, &dwHandle);
    if (dwVersionInfoSize == 0) {
        // 无版本信息时返回文件名（不含.exe）
        QString fileName = QString::fromWCharArray(szExePath);
        return fileName.section('\\', -1).section('.', 0, 0);
    }

    // 4. 读取版本信息
    std::vector<BYTE> versionInfo(dwVersionInfoSize);
    if (!GetFileVersionInfoW(szExePath, dwHandle, dwVersionInfoSize, versionInfo.data())) {
        return QStringLiteral("未知进程");
    }

    // 5. 解析版本信息中的语言和代码页
    UINT len = 0;
    LPVOID pTranslate = nullptr;
    if (!VerQueryValueW(versionInfo.data(), L"\\VarFileInfo\\Translation", &pTranslate, &len) || len == 0) {
        return QStringLiteral("未知进程");
    }

    // 6. 提取显示名称（优先尝试ProductName，其次FileDescription）
    WORD* pLangCodePage = static_cast<WORD*>(pTranslate);
    QString subBlock;
    QString displayName;

    // 遍历所有语言代码页组合（通常第一个是中文）
    for (unsigned int i = 0; i < len / sizeof(WORD) / 2; ++i) {
        WORD lang = pLangCodePage[2 * i];
        WORD codePage = pLangCodePage[2 * i + 1];

        // 构建子块路径（如“\\StringFileInfo\\080404B0\\ProductName”）
        subBlock = QString("\\StringFileInfo\\%1%2\\ProductName")
                     .arg(lang, 4, 16, QChar('0'))
                     .arg(codePage, 4, 16, QChar('0'));
        displayName = GetStringFromVersionInfo(versionInfo.data(), subBlock);

        // 如果获取ProductName失败，尝试FileDescription
        if (displayName.isEmpty()) {
            subBlock = QString("\\StringFileInfo\\%1%2\\FileDescription")
                         .arg(lang, 4, 16, QChar('0'))
                         .arg(codePage, 4, 16, QChar('0'));
            displayName = GetStringFromVersionInfo(versionInfo.data(), subBlock);
        }

        if (!displayName.isEmpty()) {
            break; // 找到有效名称则退出
        }
    }

    // 7. 若仍无结果，返回文件名（不含.exe）
    if (displayName.isEmpty()) {
        QString fileName = QString::fromWCharArray(szExePath);
        displayName = fileName.section('\\', -1).section('.', 0, 0);
    }

    return displayName;
}


// 用于在枚举窗口时传递参数的结构体
struct EnumParam {
    DWORD targetPid;               // 目标进程ID
    QList<QString> titles;   // 存储找到的窗口标题
};

// 窗口枚举回调函数
static BOOL CALLBACK EnumWindowsCallback(HWND hwnd, LPARAM lParam) {
    EnumParam* param = reinterpret_cast<EnumParam*>(lParam);

    // // 只处理可见窗口
    // if (!IsWindowVisible(hwnd)) {
    //     return TRUE; // 继续枚举
    // }

    // 获取窗口所属进程ID
    DWORD windowPid;
    GetWindowThreadProcessId(hwnd, &windowPid);

    // 检查是否匹配目标进程ID
    if (windowPid != param->targetPid) {
        return TRUE; // 继续枚举
    }

    // 获取窗口标题长度
    int titleLength = GetWindowTextLengthW(hwnd);
    if (titleLength <= 0) {
        return TRUE; // 无标题，继续枚举
    }

    // 分配缓冲区并读取窗口标题
    std::vector<WCHAR> titleBuffer(titleLength + 1); // +1 用于终止符
    int copiedLength = GetWindowTextW(hwnd, titleBuffer.data(), titleLength + 1);
    if (copiedLength > 0) {
        // 转换为QString并添加到结果列表
        param->titles.push_back(QString::fromWCharArray(titleBuffer.data(), copiedLength));
    }

    return TRUE; // 继续枚举其他窗口
}

/**
 * 根据进程ID获取窗口标题
 * @param pid 目标进程ID
 * @param allTitles 是否返回所有窗口标题（默认只返回第一个）
 * @return 窗口标题列表（默认返回第一个非空标题）
 */
QString GetWindowTitleByPid(DWORD pid, bool allTitles = false) {
    EnumParam param;
    param.targetPid = pid;

    // 枚举所有顶层窗口
    EnumWindows(EnumWindowsCallback, reinterpret_cast<LPARAM>(&param));

    // 过滤空标题
    auto it = std::remove_if(param.titles.begin(), param.titles.end(),
        [](const QString& title) { return title.isEmpty(); });
    param.titles.erase(it, param.titles.end());

    if (param.titles.isEmpty()) {
        return QStringLiteral("(无可见窗口)");
    }

    // 如果需要所有标题，用换行分隔；否则返回第一个
    return allTitles ? param.titles.join("\n") : param.titles.first();
}


QString main2() {
    QString str ;
    // 枚举所有音频会话
    std::vector<AudioSessionInfo> sessions = EnumAudioSessions();

    // std::wcout << L"检测到的音频应用程序列表:" << std::endl;
    // std::wcout << L"----------------------------------------" << std::endl;

    // 显示所有音频会话信息
    for (size_t i = 0; i < sessions.size(); i++) {
        std::wcout << L"[" << i << L"] "
                   << sessions[i].appName << L" (PID: " << sessions[i].processId << L")" << std::endl;
        qDebug() << "[" << i << "] "
                          << QString::fromStdWString(sessions[i].appName)
                          << " (PID: " << sessions[i].processId << ")";
        // QString qstr = QString::fromStdWString(wstr);
        // qDebug() << "[" << i << "] "
        //                   << WcharToChar(sessions[i].appName)
        //                   << " (PID: " << sessions[i].processId << ")";

        std::wcout << L"音量   " << (int)(sessions[i].volume * 100) << L"%"  << std::endl;
        // std::wcout << L"状态" << (sessions[i].isMuted ? L"已静音" : L"正常") << std::endl;
        qDebug() <<  (sessions[i].isMuted? "true" :"false");
        qDebug() <<"----------------------------------------" <<GetProcessNameByPid(30984);
        // str += /*GetProcessDisplayName(sessions[i].processId) */ getProcessFriendlyName(sessions[i].processId) ;
        // str += /*GetProcessDisplayName(sessions[i].processId) */ GetProcessDisplayName(30984) ;
        str += /*GetProcessDisplayName(sessions[i].processId) */ QString::fromStdWString(sessions[i].appName) ;
        str += "   ";

    }
    // str += GetProcessDisplayName(30984);
    // str += GetProcessDisplayName(10088);

    // 示例: 设置第一个应用的音量为50%
    if (!sessions.empty()) {
        bool success = SetSessionVolume(sessions[0].sessionControl, 0.9f);
        if (success) {
            std::wcout << L"已将 " << sessions[0].appName << L" 的音量设置为50%" << std::endl;
        }
    }

    // 释放所有会话接口
    for (auto& session : sessions) {
        SafeRelease(session.sessionControl);
    }

    CoUninitialize();
    return str;
}




VolumeControlWidget::VolumeControlWidget(QWidget *parent)
    : QWidget{parent}
{
    // // // 设置本地环境为中文，确保宽字符正确转换
    // std::setlocale(LC_ALL, "zh-CN.UTF-8");

   QString str="1111  " ;
   str +=  main2();
   // this->setToolTip(str);
   QLabel *b = new QLabel(this);
   b->setText(str);
   b->show();


   int masterVol;
   QList<AudioSessionInfo2> allVolumes = GetAllAudioVolumes(masterVol);

   qDebug() << "系统主音量：" << masterVol << "%";
   qDebug() << "所有音频会话音量：";
   foreach (const AudioSessionInfo2& info, allVolumes) {
       qDebug() << QString("%1 (%2) - %3% %4")
                    .arg(info.name)
                    .arg(info.exeName)
                    .arg(info.volume)
                    .arg(info.isSystemSound ? "(系统声音)" : "");
   }


}
